#ifndef XTIME_HEADER_H
#define XTIME_HEADER_H

const int MILLISECONDS_PER_SECOND = 1000;
const int NANOSECONDS_PER_SECOND = 1000000000;
const int NANOSECONDS_PER_MILLISECOND = 1000000;

const int MICROSECONDS_PER_SECOND = 1000000;
const int NANOSECONDS_PER_MICROSECOND = 1000;

struct xtime {

    typedef int xtime_sec_t;
    typedef int xtime_usec_t;

    xtime_sec_t sec;
    xtime_usec_t nsec;

    static void now(xtime& xt);
};


inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
    if (xt1.sec == xt2.sec)
        return (int)(xt1.nsec - xt2.nsec);
    else 
        return (xt1.sec > xt2.sec) ? 1 : -1;
}


void xtime::now(xtime& xt) {
    FILETIME ft;
    GetSystemTimeAsFileTime(&ft);

    typedef unsigned __int64 uint64;
    static const uint64 TIMESPEC_TO_FILETIME_OFFSET = 116444736000000000;
    const uint64 ft64 =
        (static_cast<uint64>(ft.dwHighDateTime) << 32)
        + ft.dwLowDateTime;

    xt.sec = static_cast<xtime::xtime_sec_t>(
        (ft64 - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);

    xt.nsec = static_cast<xtime::xtime_usec_t>(
        ((ft64 - TIMESPEC_TO_FILETIME_OFFSET) % 10000000) * 100);
}

inline void 
to_duration(xtime xt, int& milliseconds)
{
    xtime cur;
    xtime::now(cur);

    if (xtime_cmp(xt, cur) <= 0)
        milliseconds = 0;
    else {
        if (cur.nsec > xt.nsec) {
            xt.nsec += NANOSECONDS_PER_SECOND;
            --xt.sec;
        }
        milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
            NANOSECONDS_PER_MILLISECOND);
    }
}


#endif